package middleware

import (
	"encoding/json"
	"net"
	"net/http"
	"strconv"
	"strings"

	"github.com/ammyhaber/seckill/pkg/limiter"
)

// UserIPLimiterMiddleware 基于用户ID和IP的限流中间件
func UserIPLimiterMiddleware(userLimiter *limiter.UserRateLimiter, ipLimiter *limiter.IPRateLimiter) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// 1. 提取用户ID（假设在URL参数或请求体中）
			userID := extractUserID(r)

			// 2. 提取客户端IP
			clientIP := extractClientIP(r)

			// 3. 如果有用户ID，先检查用户限流
			if userID != "" && userLimiter != nil {
				if !userLimiter.AllowUser(userID) {
					w.Header().Set("Content-Type", "application/json")
					w.WriteHeader(http.StatusTooManyRequests)
					json.NewEncoder(w).Encode(map[string]string{
						"status":  "error",
						"message": "该用户请求频率过高，请稍后再试",
					})
					return
				}
			}

			// 4. 检查IP限流
			if clientIP != "" && ipLimiter != nil {
				if !ipLimiter.AllowIP(clientIP) {
					w.Header().Set("Content-Type", "application/json")
					w.WriteHeader(http.StatusTooManyRequests)
					json.NewEncoder(w).Encode(map[string]string{
						"status":  "error",
						"message": "当前IP请求频率过高，请稍后再试",
					})
					return
				}
			}

			// 5. 限流通过，继续处理请求
			next.ServeHTTP(w, r)
		})
	}
}

// extractUserID 提取请求中的用户ID
func extractUserID(r *http.Request) string {
	// 尝试从URL参数获取
	userIDStr := r.URL.Query().Get("user_id")
	if userIDStr != "" {
		return userIDStr
	}

	// 尝试从请求体中解析（对于POST请求）
	if r.Method == http.MethodPost && r.Body != nil {
		// 只在Content-Type为JSON时尝试解析
		contentType := r.Header.Get("Content-Type")
		if strings.Contains(contentType, "application/json") {
			// 不要完全读取body，会影响后续处理
			// 这里仅作示例，实际项目中应考虑更优的方案
			var body struct {
				UserID int64 `json:"user_id"`
			}

			// 创建一个decoder不会消耗body
			decoder := json.NewDecoder(r.Body)
			// 只预览，不消费
			decoder.Buffered()
			err := decoder.Decode(&body)
			if err == nil && body.UserID > 0 {
				return strconv.FormatInt(body.UserID, 10)
			}
			// 重置body供后续使用
			r.Body.Close()
		}
	}

	return ""
}

// extractClientIP 提取客户端真实IP
func extractClientIP(r *http.Request) string {
	// 尝试从X-Forwarded-For头获取
	xForwardedFor := r.Header.Get("X-Forwarded-For")
	if xForwardedFor != "" {
		// X-Forwarded-For可能包含多个IP，取第一个
		parts := strings.Split(xForwardedFor, ",")
		if len(parts) > 0 {
			clientIP := strings.TrimSpace(parts[0])
			if isValidIP(clientIP) {
				return clientIP
			}
		}
	}

	// 尝试从X-Real-IP头获取
	xRealIP := r.Header.Get("X-Real-IP")
	if xRealIP != "" {
		if isValidIP(xRealIP) {
			return xRealIP
		}
	}

	// 从RemoteAddr获取
	remoteAddr := r.RemoteAddr
	ip, _, err := net.SplitHostPort(remoteAddr)
	if err == nil && isValidIP(ip) {
		return ip
	}

	return ""
}

// isValidIP 检查IP是否有效
func isValidIP(ip string) bool {
	return net.ParseIP(ip) != nil
}
